package com.hddz.comlib;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.util.Log;

import com.hddz.comlib.packet.CommandPacket;
import com.hddz.comlib.packet.HistoryPacket;
import com.hddz.comlib.packet.HistorySamplePacket;
import com.hddz.comlib.packet.MHZCommandPacket;
import com.hddz.comlib.packet.NFCPacketReceiver;
import com.hddz.comlib.packet.RealTimePacket;
import com.hddz.comlib.packet.WeekUpPacket;
import com.hddz.comlib.packet.WeekUpSamplePacket;

public class NFCSerialHelper {
	private NFCPacketReceiver nfcPacketReceiver;
	private static final String TAG = "NFCSerialHelper";
	private static final String DEVFILE_PATH = "/proc/driver/as3992";
	private static final String SERIALPORT_PATH = "/dev/eser1";

	private SerialPort mSerialPort = null;
	protected OutputStream mOutputStream;
	private InputStream mInputStream;
	private ReadThread mReadThread;
	private List<NFCPacketReceiver> packetReceivers;

	public Boolean putNFCPacketReceiver(NFCPacketReceiver receiver) {
		synchronized (packetReceivers) {
			if (packetReceivers.indexOf(receiver) == -1) {
				packetReceivers.add(receiver);
			}
		}
		return true;
	}

	public Boolean removeNFCPacketReceiver(NFCPacketReceiver receiver) {
		synchronized (packetReceivers) {
			if (packetReceivers.indexOf(receiver) != -1) {
				return packetReceivers.remove(receiver);
			}
		}
		return true;
	}

	/**
	 * 连接NFC串口，开始读取
	 * 
	 * @return
	 */
	public Boolean startNFCSerial() {
		packetReceivers = new ArrayList<NFCPacketReceiver>();
		try {
			mSerialPort = new SerialPort(new File(SERIALPORT_PATH), 19200, 0);
			mOutputStream = mSerialPort.getOutputStream();
			mInputStream = mSerialPort.getInputStream();
			mReadThread = new ReadThread();
			mReadThread.start();
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 停止NFC串口
	 * 
	 * @return
	 */
	public Boolean stopNFCSerial() {
		packetReceivers.clear();
		try {
			if (mReadThread != null)
				mReadThread.interrupt();
			if (mSerialPort != null) {
				mSerialPort.close();
				mSerialPort = null;
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 发送数据到NFC
	 * 
	 * @param buf
	 * @return
	 */
	public Boolean sendToNFC(byte[] buf) {
		try {
			mOutputStream.write(buf);
			mOutputStream.flush();
			String s = "";
			for (int i = 0; i < buf.length; i++) {
				s += String.format("%X ", buf[i]);
			}
			Log.d(TAG, "send=>" + s);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public Boolean sendToNFC(String buf) {
		Log.d(TAG, "send=>" + buf);
		return sendToNFC(buf.getBytes());
	}

	/**
	 * 实时数据事件
	 * 
	 * @param packet
	 */
	private void receivedRealTimePacket(RealTimePacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedRealTimePacket(packet);
			}
		}
	}

	/**
	 * 历史包数据事件
	 * 
	 * @param packet
	 */
	private void receivedHistoryPacket(HistoryPacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedHistoryPacket(packet);
			}
		}
	}

	/**
	 * 命令包数据事件
	 * 
	 * @param packet
	 */
	private void receivedCommandPacket(CommandPacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedCommandPacket(packet);
			}
		}
	}

	/**
	 * MHZ数据事件
	 * 
	 * @param packet
	 */
	private void receivedMHZCommandPacket(MHZCommandPacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedMHZCommandPacket(packet);
			}
		}
	}

	/**
	 * 收到唤醒报文
	 * 
	 * @param packet
	 */
	private void receivedWeekUpPacket(WeekUpPacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedWeekUpPacket(packet);
			}
		}
	}

	/**
	 * 收到唤醒报文
	 */
	private void receivedWeekUpSamplePacket(WeekUpSamplePacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedWeekUpSamplePacket(packet);
			}
		}
	}

	private void receivedHistorySamplePacket(HistorySamplePacket packet) {
		synchronized (packetReceivers) {
			for (NFCPacketReceiver receiver : packetReceivers) {
				receiver.OnReceivedHistorySamplePacket(packet);
			}
		}
	}

	private int countSum = 0;

	class ReadThread extends Thread {
		private ByteBuffer r_bBuf = ByteBuffer.allocate(1024 * 10);
		private byte[] buffer = new byte[1024];
		private int size = 0;

		private Date date = new Date();

		@Override
		public void run() {
			super.run();
			r_bBuf.mark();
			while (!isInterrupted()) {
				size = 0;
				try {
					if (mInputStream == null)
						return;
					size = mInputStream.read(buffer);
					if (size > 0) {
						if (size > 0) {
							if ((new Date().getTime() - date.getTime()) / 1000 > 40) {
								date = new Date();
								Log.d(TAG, "countSum重置");
								countSum = 0;
							}
							countSum += size;
							Log.d(TAG, "本次：" + size + " 合计：" + countSum);
							// continue;
						}
						if (r_bBuf.remaining() < size) {
							r_bBuf.limit(r_bBuf.position());//
							r_bBuf.reset();// position到有效记录位起始
							r_bBuf.compact();
							r_bBuf.mark();
						}
						r_bBuf.put(buffer, 0, size);
						String s = "";
						for (int i = 0; i < size; i++) {
							s += String.format("%2X ", buffer[i]);
						}
						Log.d(TAG, "receive：" + s);

						r_bBuf.limit(r_bBuf.position());// 设置结尾，开始读取数据
						r_bBuf.reset();// 开始读取
						Log.d(TAG, "zero limit=" + r_bBuf.limit() + " position=" + r_bBuf.position() + " remaining=" + r_bBuf.remaining());
						if (r_bBuf.remaining() < 5) {
							r_bBuf.mark();
							r_bBuf.position(r_bBuf.limit());
							r_bBuf.limit(r_bBuf.capacity());
							continue;
						}
						Log.d(TAG, "first limit=" + r_bBuf.limit() + " position=" + r_bBuf.position() + " remaining=" + r_bBuf.remaining());
						while (r_bBuf.remaining() > 3) {
							int flag = (r_bBuf.get() & 0xff);
							// Log.d(TAG, "flag=" + flag);
							r_bBuf.mark();
							if (flag == 170 || flag == 187 || flag == 204 || flag == 221 || flag == 238 || flag == 172) {
								if (flag != (r_bBuf.get() & 0xff)) { // 两个标签
									r_bBuf.reset();
									continue;
								}
								int len = (r_bBuf.get() & 0xff);// 获取报文长度
								if (len > r_bBuf.remaining() - 2) {// 不够一个数据包的长度
									r_bBuf.position(r_bBuf.position() - 3);// 回到双标志位之前
									r_bBuf.mark();// 记录上次读到的标志位
									r_bBuf.position(r_bBuf.limit());// 准备写入
									r_bBuf.limit(r_bBuf.capacity());// 准备写入
									break;
								}
								r_bBuf.mark();// 为准备跳到结尾部分做准备
								r_bBuf.position(r_bBuf.position() + len);// 跳过数据位

								if ((r_bBuf.get() & 0xff) == 13 && (r_bBuf.get() & 0xff) == 10) {// 查看结尾是否正确
									r_bBuf.reset();
									// Log.d(TAG, "flag=" + flag);
									if (flag == 170) {// 历史数据
										HistoryPacket history = new HistoryPacket();
										if (history.parse(r_bBuf, len)) {
											receivedHistoryPacket(history);
										}
										history = null;
									} else if (flag == 187) {// 实时数据
										RealTimePacket real = new RealTimePacket();
										if (real.parse(r_bBuf, len)) {
											receivedRealTimePacket(real);
										}
									} else if (flag == 204) {// 指令
										CommandPacket command = new CommandPacket();
										if (command.parse(r_bBuf, len)) {
											receivedCommandPacket(command);
										}
									} else if (flag == 221) {// NFC_R控制指令
										MHZCommandPacket command = new MHZCommandPacket();
										if (command.parse(r_bBuf, len)) {
											receivedMHZCommandPacket(command);
										}
									} else if (flag == 238) {// NFC_T 唤醒指令

										Log.d(TAG, "唤醒报文=");
										if (len == 6) {// 老板的唤醒报文
											WeekUpPacket command = new WeekUpPacket();
											if (command.parse(r_bBuf, len)) {
												receivedWeekUpPacket(command);
											}
										} else {
											WeekUpSamplePacket command = new WeekUpSamplePacket();
											if (command.parse(r_bBuf, len)) {
												receivedWeekUpSamplePacket(command);
											}
										}
									} else if (flag == 172) {
										HistorySamplePacket history = new HistorySamplePacket();
										if (history.parse(r_bBuf, len)) {
											receivedHistorySamplePacket(history);
										}
										history = null;
									} else {
										r_bBuf.position(r_bBuf.position() + len);
									}
									Log.d(TAG, "flag=" + flag + " xxxxxx limit=" + r_bBuf.limit() + " position=" + r_bBuf.position());
									r_bBuf.position(r_bBuf.position() + 2);
								} else { // 如果结尾不正确，则回退到双标签位的下一位
									r_bBuf.reset();
									r_bBuf.position(r_bBuf.position() - 2);// 回到双标签位的下一位
								}
							}
						} //
						if (r_bBuf.remaining() == 0) { //
							r_bBuf.clear(); //
							r_bBuf.mark();
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
		}
	}
}
